from character_analyze import Lexical
from character_analyze import Fam
class Semantic:
    table = [] #符号表 0表示全局变量表，1表示局部栈
    temp_table = [] #临时变量表
    const_table = [] #常量表
    quaternion = [] #四元式
    level = 0 #记录当前块的层级
    row = 0 #记录当前程序所在行数
    var_block = 0 #记录当前所在块的位置
    temp_name = 0
    main_pos = -1 #记录main函数在四元式的位置
    # 常量编码
    const_code = {'double': 1, 'float': 2, 'int': 3, 'char': 4} #5表示关键字
    def __init__(self):
        self.const_table_len = 0 #常数表长度
        self.temp_table_len = 0 #临时变量表长度
        self.qua_len = 0 #四元式表长度
    def newtemp(self):
        new_table = ['', ''] #新的临时变量,第0项是名字，第一项是类型
        new_table[0] = 'T' + str(self.temp_name)
        self.temp_name += 1
        self.temp_table.append(new_table)
        self.temp_table_len += 1
        #0表示符号表,1表示临时表,2表示常量表
        return [1, self.temp_table_len - 1] #返回入口地址
    #添加常量入常量表，返回常量在表中地址
    def addconst(self, const_value, const_type):
        const_type = self.const_code[const_type]
        if const_type == self.const_code['char']:
            const_value = '\'' + const_value + '\''
        self.const_table.append([const_value, const_type])
        self.const_table_len += 1
        return [2, self.const_table_len - 1] #返回入口地址
    #添加全局变量
    def addtable(self, var_names, species, var_type): #名字表,种属,类型， 
        var_type = self.const_code[var_type]
        if species == 0 or species == 1: #是全局变量或函数
            self.check_dup(var_names, species) #查重
            temp = [0] #0表示全局变量表
            for var_name in var_names:
                temp.append([var_name, species, var_type]) #名字，种属，类型
            self.table.append(temp)
        else:
            raise Exception('错误调用addtable')
    #查找全局变量是否已定义
    def check_dup(self, var_names, species):
        #遍历所有全局变量表
        for sub_table in self.table:
            if sub_table[0] == 0: #是全局变量表
                for sub_sub_table in sub_table[1:]: #遍历全局变量表中的所有变量
                    for var_name in var_names: #对每个变量查重
                        if sub_sub_table[0] == var_name and sub_sub_table[1] == species:
                            raise Exception('redefinition of {} on line {}'.format(var_name, self.row))
    #添加局部变量
    def addlocal(self, var_names, species, var_type):
        var_type = self.const_code[var_type]
        if species == 0: #是局部变量
            self.check_duo_loc(var_names, species)
            for var_name in var_names:
                self.table[-1][-1].append([var_name, 0, var_type, 1, 0])
    #查重局部变量
    def check_duo_loc(self, var_names, species):
        for var in self.table[-1][-1][1:]: #只在当前块中查重
            for var_name in var_names:
                if var[0] == var_name:
                    if var[1] == species:
                        raise Exception('redefinition of {} on line {}'.format(var_name, self.row))
    #查找变量在符号表中的入口地址
    def find_var(self, var_name):
        #先查当前块
        for var, var_pos in zip(self.table[-1][self.var_block][1:], range(len(self.table[-1][self.var_block]) - 1)):
            if var[0] == var_name and var[1] == 0:
                return [0, 1, 0, self.var_block, var_pos + 1]
        #再查栈内块
        for block, block_pos in zip(self.table[-1][1:][::-1], range(len(self.table[-1]) - 1)):
            if block[0] < self.level: #只查层级高的
                for var, var_pos in zip(block[1:], range(len(block) - 1)):
                    if var[0] == var_name and var[1] == 0:
                        return [0, 1, 0, len(self.table[-1]) - block_pos - 1, var_pos + 1]
        #再查全局变量
        for overall, overall_pos in zip(self.table, range(len(self.table))):
            if overall[0] == 0: #判断是否是全局表
                for var, var_pos in zip(overall[1:], range(len(overall) - 1)):
                    if var[0] == var_name and var[1] == 0:
                        return [0, 0, overall_pos, 0, var_pos + 1]
        return [-1]
    #查找标号在符号表的入口地址,若没有返回-1
    def find_label(self, label_name):
        #现查当前块
        for label, label_pos in zip(self.table[-1][self.var_block][1:], range(len(self.table[-1][self.var_block]) - 1)):
            if label[0] == label_name and label[1] == 2:
                return [0, 1, 0, self.var_block, label_pos + 1]
        #再查栈内块
        for block, block_pos in zip(self.table[-1][1:], range(len(self.table[-1]) - 1)):
            for label, label_pos in zip(block[1:], range(len(block) - 1)):
                if label[0] == label_name and label[1] == 2:
                    return [0 ,1, 0, block_pos + 1, label_pos + 1]
        return [-1]
    #查找函数在符号表的入口地址
    def find_func(self, func_name):
        for overall, overall_pos in zip(self.table, range(len(self.table))):
            if overall[0] == 0: #是全局变量表
                if overall[1][1] == 1 and overall[1][0] == func_name:
                    return [0, 0, overall_pos, 0, 1]
        return [-1]
    #根据地址找到符号表中的变量,返回变量和类型
    def find_operator(self, op_addr):
        if op_addr[0] == 0: #在符号表中
            if op_addr[1] == 0: #在全局表中
                operator = self.table[op_addr[2]][op_addr[4]]
            elif op_addr[1] == 1: #在局部栈中
                operator = self.table[-1][op_addr[3]][op_addr[4]]
            op_type = operator[2]
        elif op_addr[0] == 1: #在临时变量表中
            operator = self.temp_table[op_addr[1]]
            op_type = operator[1]
        elif op_addr[0] == 2: #在常量表中
            operator = self.const_table[op_addr[1]]
            op_type = operator[1]
        return operator, op_type
    #四元式入表
    def addqua(self, operator, op1, op2, temp):
        self.quaternion.append([operator, op1, op2, temp])
        self.qua_len += 1
    #列表回填
    def backpatch(self, exports, position): #出口列表，回填地址
        for export in exports:
            self.quaternion[export][3] = position
    #拉链回填
    def backfill(self, export, position): 
        linkhead = self.quaternion[export][3]
        self.quaternion[export][3] = position
        while linkhead != -1:
            export = linkhead
            linkhead = self.quaternion[export][3]
            self.quaternion[export][3] = position
    #根据全局变量中函数的地址找到形参块，在函数栈的地址中找到变量类型和个数，判断与arglist是否匹配
    def judge_matches(self, func_name, func_place, arglist):
        func_place[2]
        func_block = self.table[func_place[2] + 1][1]
        if (len(func_block) - 1) != len(arglist):
            if (len(func_block) - 1) < len(arglist):
                raise Exception("too many arguments to function {} on line {}".format(func_name, self.row))
            else:
                raise Exception("too few arguments to function {} on line {}".format(func_name, self.row))
        reallist = [] #存放形参类型
        for arg_addr in arglist:
            reallist.append(self.find_operator(arg_addr)[1])
        for formal_par, real_par in zip(func_block[1:], reallist):
            if formal_par[2] != real_par:
                raise Exception("Inconsistent type on line {}".format(self.row))
    #判断要返回的临时变量与函数返回类型是否匹配,返回函数要返回的临时变量地址
    def judge_return(self, T_addr):
        func_type = self.table[-2][1][2]
        T, T_type = self.find_operator(T_addr) #得到返回值和返回类型
        if (func_type == 1 or func_type == 2) and (T_type == 3 or T_type == 4):
            T1_addr = self.newtemp() #产生临时变量
            self.temp_table[T1_addr[1]][1] = func_type #临时变量添加类型
            #产生四元式
            self.addqua('itr', T[0], '_', self.temp_table[T1_addr[1]][0]) #强制类型转换
            return T1_addr
        elif (func_type == 3 or func_type == 4) and (T_type == 1 or T_type == 2):
            T1_addr = self.newtemp() #产生临时变量
            self.temp_table[T1_addr[1]][1] = func_type #临时变量添加类型
            #产生四元式
            self.addqua('rti', T[0], '_', self.temp_table[T1_addr[1]][0]) #强制类型转换
            return T1_addr
        else:
            self.temp_table[T_addr[1]][1] = func_type #临时变量修改类型
            return T_addr
    #临时变量添加类型，根据符号表入口地址产生四元式
    def gen(self, operator, op1_addr, op2_addr, temp_addr):
        if op1_addr == '_' and op2_addr == '_': 
            if operator == 'push' or operator == 'pop': #函数实参或函数返回值
                temp, _ = self.find_operator(temp_addr) 
                self.addqua(operator, '_', '_', temp[0])
            else: #转移指令
                self.addqua(operator, '_', '_', temp_addr)
        elif op2_addr =='_':
            op1, op1_type = self.find_operator(op1_addr) #op1为操作数，op1_type为操作数类型
            if operator == '!' or operator == '-':
                self.temp_table[temp_addr[1]][1] = op1_type #临时变量添加类型
                if operator == '-':
                    operator = '@'
                self.addqua(operator, op1[0], '_', self.temp_table[temp_addr[1]][0])
            elif operator == '++' or operator == '--': #没有临时变量
                self.addqua(operator[0], op1[0], 1, op1[0])
            elif operator == ':=': #为临时变量赋值
                self.temp_table[temp_addr[1]][1] = op1_type #临时变量添加类型
                self.addqua(operator, op1[0], '_', self.temp_table[temp_addr[1]][0])
            elif operator == '=': #赋值语句,左值为id
                op2, op2_type = self.find_operator(temp_addr) #左值id
                if (op1_type == 1 or op1_type == 2) and (op2_type == 3 or op2_type == 4) or (op2_type == 1 or op2_type == 2) and (op1_type == 3 or op1_type == 4):
                    if (op1_type == 1 or op1_type == 2) and (op2_type == 3 or op2_type == 4):
                        switch = 'rti'
                    else:
                        switch = 'itr'
                    T_addr = self.newtemp()
                    self.temp_table[T_addr[1]][1] = op2_type #临时变量添加类型
                    self.addqua(switch, op1[0], '_', self.temp_table[T_addr[1]][0]) #强制类型转换
                    self.addqua(':=', self.temp_table[T_addr[1]][0], '_', op2[0])#赋值产生四元式
                else:
                    self.addqua(':=', op1[0], '_', op2[0])
            elif operator == '+=' or operator == '-=' or operator == '*=' or operator == '/=' or operator == '%=' or operator == '<<=' or operator == '>>=':
                operator = operator[:-1]
                T_addr = self.newtemp()
                self.gen(operator, temp_addr, op1_addr, T_addr)
                self.gen('=', T_addr, '_', temp_addr)
            elif operator == 'jnz' or operator == 'jz':
                self.addqua(operator, op1[0], '_', temp_addr)
        else:
            op1, op1_type = self.find_operator(op1_addr) #op1为操作数，op1_type为操作数类型
            op2, op2_type = self.find_operator(op2_addr) #op1为操作数，op1_type为操作数类型
            if operator == '+' or operator == '-' or operator == '*' or operator == '/':
                if (op1_type == 1 or op1_type == 2) and (op2_type == 3 or op2_type == 4):
                    T_addr = self.newtemp() #产生临时变量
                    self.temp_table[T_addr[1]][1] = op1_type #临时变量添加类型
                    self.temp_table[temp_addr[1]][1] = op1_type #操作结果添加类型
                    #产生四元式
                    self.addqua('itr', op2[0], '_', self.temp_table[T_addr[1]][0]) #强制类型转换
                    self.addqua(operator, op1[0], self.temp_table[T_addr[1]][0], self.temp_table[temp_addr[1]][0])
                elif (op2_type == 1 or op2_type == 2) and (op1_type == 3 or op1_type == 4):
                    T_addr = self.newtemp()
                    self.temp_table[T_addr[1]][1] = op2_type
                    self.temp_table[temp_addr[1]][1] = op2_type #临时变量添加类型
                    #产生四元式
                    self.addqua('itr', op1[0], '_', self.temp_table[T_addr[1]][0])
                    self.addqua(operator, self.temp_table[T_addr[1]][0], op2[0], self.temp_table[temp_addr[1]][0])
                else:
                    self.temp_table[temp_addr[1]][1] = op1_type #临时变量添加类型
                    self.addqua(operator, op1[0], op2[0], self.temp_table[temp_addr[1]][0])
            elif operator == '%' or operator == '<<' or operator == '>>':
                if op1_type == 1 or op1_type == 2 or op2_type == 1 or op2_type == 2:
                    raise Exception('invalid operands to binary % on line {}'.format(self.row))
                else:
                    self.temp_table[temp_addr[1]][1] = op1_type #临时变量添加类型
                    #产生四元式
                    if operator == '<<':
                        operator = 'shl'
                    elif operator == '>>':
                        operator = 'shr'
                    self.addqua(operator, op1[0], op2[0], self.temp_table[temp_addr[1]][0])
            elif operator == '>' or operator == '<' or operator == '>=' or operator == '<=':
                self.temp_table[temp_addr[1]][1] = self.const_code['int'] #操作结果添加类型
                self.addqua('j' + operator, op1[0], op2[0], self.qua_len + 3)
                self.addqua(':=', '0', '_', self.temp_table[temp_addr[1]][0])
                self.gen('jp', '_', '_', self.qua_len + 2)
                self.addqua(':=', '1', '_', self.temp_table[temp_addr[1]][0])
            elif operator == '==' or operator == '!=':
                T_addr = self.newtemp()
                self.temp_table[T_addr[1]][1] = self.const_code['int'] #临时变量添加类型
                self.temp_table[temp_addr[1]][1] = self.const_code['int'] #操作结果添加类型
                self.addqua('cmp', op1[0], op2[0], self.temp_table[T_addr[1]][0])
                if operator == '==':
                    self.gen('jz', T_addr, '_', self.qua_len + 3)
                else:
                    self.gen('jnz', T_addr, '_', self.qua_len + 3)
                self.addqua(':=', '0', '_', self.temp_table[temp_addr[1]][0])
                self.gen('jp', '_', '_', self.qua_len + 2)
                self.addqua(':=', '1', '_', self.temp_table[temp_addr[1]][0])
class Syntax:
    aheadp = 0
    sem = Semantic() #语义类
    def __init__(self, codes):
        self.codes = codes
        self.codes.append(('#', '#'))
    def getsym(self):
        while True:
            if self.codes[self.aheadp] == '\n': #如果是换行符,行数+1
                self.aheadp += 1
                self.sem.row += 1
                continue
            else:
                self.aheadp += 1
                return self.codes[self.aheadp - 1] #返回指针指向的当前值
    def recall(self): #指针回溯
        self.aheadp -= 1
        while self.codes[self.aheadp - 1] == '\n':
            self.aheadp -= 1
            self.sem.row -= 1
        return self.codes[self.aheadp - 1]
    def relocat(self, position, row): #根据位置重新定位指针
        self.aheadp = position
        self.sem.row = row
        self.sym = self.codes[self.aheadp - 1]
    def main(self):
        self.sym = self.getsym()
        self.start() #第一个非终结符
        if self.sym == ('#', '#'):
            print('Finish analyze')
        else:
            print(self.sym)
            raise Exception("Sytax Error")
    def start(self): #程序开始
        self.sem.addqua('jp', '_', '_', 0) #跳转到主函数所在行数
        self.Z()
        while self.sym[1] == 'main' or self.sym[0] == 0:
            self.Z()
        if self.sem.main_pos == -1:
            raise Exception("undefined reference to {}".format("'WinMain'"))
    def Z(self): #声明语句或函数
        if self.sym[0] == 0:
            position = self.aheadp
            row = self.sem.row
            try:
                self.declare()
            except:
                self.relocat(position, row)
                self.func()
        elif self.sym[1] == 'main':
            self.manfunc()
    def declare(self): #全局变量
        var_type = self.C()
        var_names = self.D()
        if self.sym[0] == ';':
            self.sym = self.getsym()
            self.sem.addtable(var_names, 0, var_type) #填入符号表,0表示变量
        else:
            if self.sym[1] == '_':
                raise Exception("[Sytax Error] expected {} before {} on line {}".format('\';\'',self.sym[0], self.sem.row))
            else:
                raise Exception("[Sytax Error] expected {} before {} on line {}".format('\';\'',self.sym[1], self.sem.row))
    def func(self): #函数
        func_type = self.C() #得到函数类型
        func_name = self.E() #得到函数名
        self.sem.addtable([func_name], 1, func_type) #函数填入符号表,1表示函数
        if self.sym[0] == '(':
            self.sym = self.getsym()
            #创建函数局部栈
            self.sem.table.append([1]) #建立新的局部符号栈
            self.sem.table[-1].append([0]) #形参块，层级最高
            self.params() #产生四元式，从栈中取变量，变量填入符号表
            if self.sym[0] == ')':
                self.sym = self.getsym()
                control = [[],[]]
                self.block(control)
                if len(control[0]) != 0:
                    raise Exception("[Error] break statement not within loop on line {}".format(control[0][0][0]))
                if len(control[1]) != 0:
                    raise Exception("[Error] continue statement not within loop on line {}".format(control[1][0][0]))
                T1_place = self.sem.newtemp()
                self.sem.temp_table[T1_place[1]][1] = self.sem.const_code['int'] #临时变量类型为整型
                self.sem.gen('pop', '_', '_', T1_place) #从栈中取出返回地址给临时变量
                self.sem.addqua('jp', '_', '_', self.sem.temp_table[T1_place[1]][0]) #跳转到临时变量的位置
            else:
                if self.sym[1] == '_':
                    raise Exception("[Sytax Error] expected declaration specifiers or \'...\' before {} token on line {}".format(self.sym[0], self.sem.row))
                else:
                    raise Exception("[Sytax Error] expected declaration specifiers or \'...\' before {} token on line {}".format(self.sym[1], self.sem.row))
        else:
            if self.sym[1] == '_':
                raise Exception("[Sytax Error] expected {} before {} token on line {}".format('(', self.sym[0], self.sem.row))
            else:
                raise Exception("[Sytax Error] expected {} before {} token on line {}".format('(', self.sym[1], self.sem.row))
    def params(self): #函数形参列表
        var_type = self.C()
        var_name = self.E()
        self.sem.addlocal([var_name], 0, var_type) #填入局部栈符号表
        #产生四元式，从栈中取出变量
        self.sem.addqua('pop', '_', '_', var_name)
        while self.sym[0] == ',':
            self.sym = self.getsym()
            var_type = self.C()
            var_name = self.E()
            self.sem.addlocal([var_name], 0, var_type) #填入局部栈符号表
            #产生四元式，从栈中取出变量
            self.sem.addqua('pop', '_', '_', var_name)
        else:
            if self.sym[0] != ')': # follow ) 用空推导 
                raise Exception("[Sytax Error] expected {} on line {}".format('\')\'',self.sem.row))
    def manfunc(self): #主函数
        if self.sym[1] == 'main':
            self.sym = self.getsym()
            #记录main函数在四元式的位置
            self.sem.main_pos = self.sem.qua_len
            self.sem.quaternion[0][3] = self.sem.main_pos
            if self.sym[0] == '(':
                self.sym = self.getsym()
                if self.sym[0] == ')':
                    self.sym = self.getsym()
                    self.sem.table.append([1]) #建立新的局部符号栈
                    control = [[],[]]
                    self.block(control)
                    if len(control[0]) != 0:
                        raise Exception("[Error] break statement not within loop on line {}".format(control[0][0][0]))
                    if len(control[1]) != 0:
                        raise Exception("[Error] continue statement not within loop on line {}".format(control[1][0][0]))
                else:
                    raise Exception("[Sytax Error] expected {} at the end of input on line {}".format('\')\'', self.sem.row))
            else:
                raise Exception("[Sytax Error] expected {} at the end of input on line {}".format('\'(\'', self.sem.row))
        else:
            raise Exception("[Sytax Error] undefined reference to {} on line {}".format('WinMain', self.sem.row))
    def block(self, control): #块内代码
        if self.sym[0] == '{':
            self.sym = self.getsym()
            self.sem.level += 1 #块层级+1
            self.sem.table[-1].append([self.sem.level]) #块入符号栈
            now_block = self.sem.var_block #记录块之前所在块
            self.sem.var_block = len(self.sem.table[-1]) - 1 #记录程序当前所在块
            self.A(control)
            if self.sym[0] == '}':
                self.sym = self.getsym()
                self.sem.var_block = now_block
                self.sem.level -= 1 #块层级-1
            else:
                raise Exception("[Sytax Error] expected {} at the end of input on line {}".format('\'}\'',self.sem.row))
        else:
            raise Exception("[Sytax Error] expected identifier or {} before {} token on line {}".format('\'{\'','\'}\'',self.sem.row))
    def A(self, control): #子程序
        if self.sym[0] == 0:#求First(A)
            self.B()
            self.L(control)
        else:
            self.L(control)
    def B(self): #变量说明部分
        var_type = self.C()
        var_names = self.D()
        if self.sym[0] == ';':
            self.sym = self.getsym()
            self.sem.addlocal(var_names, 0, var_type) #填入局部栈符号表
            while self.sym[0] == 0:
                var_type = self.C()
                var_names = self.D()
                if self.sym[0] == ';':
                    self.sym = self.getsym()
                    self.sem.addlocal(var_names, 0, var_type) #填入局部栈符号表
                else:
                    raise Exception("[Sytax Error] expected {} before {} token on line {}".format('\';\'',self.sym[0],self.sem.row))  
        else:
            if self.sym[1] == '_':
                raise Exception("[Sytax Error] expected {} before {} token on line {}".format('\';\'',self.sym[0],self.sem.row))    
            else:
                raise Exception("[Sytax Error] expected {} before {} token on line {}".format('\';\'',self.sym[1],self.sem.row)) 
    def C(self): #变量说明.
        if self.sym[0] == 0:
            var_type = self.sym[1] #得到变量类型
            self.sym = self.getsym()   
            return var_type
        else:
            raise Exception("[Sytax Error] {} was not declared in this scope on line {}".format(self.sym[1],self.sem.row))
    def D(self): #标识符表
        var_names = [] #变量名表
        var_names.append(self.E())
        while self.sym[0] == ',':
            self.sym = self.getsym()
            var_names.append(self.E())
        return var_names
    def E(self): #标识符
        if self.sym[0] == 'id':
            var_name = self.sym[1]
            self.sym = self.getsym()
            return var_name
        else:
            raise Exception("[Sytax Error] declaration does not declare anything on line {}".format(self.sem.row))
    def L(self, control): #语句块
        if self.sym[0] != '}':
            chain1 = []
            self.S(chain1, control)
            #如果有拉链，回填
            if len(chain1) != 0:
                self.sem.backpatch(chain1, self.sem.qua_len)
            self.L(control)
    def S(self, chain, control): #语句
        if self.sym[0] == 'id': #可能是标号： 或者表达式语句 或者函数调用语句
            islabel = True #暂时认为是标号语句
            position = self.aheadp
            row = self.sem.row
            try:
                self.label()
            except:
                islabel = False
            if islabel:
                self.S(chain, control)
            else:
                self.relocat(position, row) #回溯
                #是表达式或布尔表达式
                position = self.aheadp
                row = self.sem.row
                isbool = False
                zipper = [[],[]]
                pre_qua_len = self.sem.qua_len
                pre_temp_name = self.sem.temp_name
                try:
                    self.exp()
                    if self.sym[0] != ';':
                        raise Exception()
                except:
                    #删掉已经产生的四元式
                    now_qua_len = self.sem.qua_len
                    self.sem.qua_len = pre_qua_len
                    self.sem.temp_name = pre_temp_name
                    for qua_index in range(now_qua_len - pre_qua_len):
                        self.sem.quaternion.pop(pre_qua_len)
                    isbool = True
                    self.relocat(position, row) #回溯
                    self.bool1(zipper)
                if self.sym[0] == ';':
                    self.sym = self.getsym()
                    if isbool:
                        #遇到分号，回填真假出口 
                        for exports in zipper:
                            self.sem.backpatch(exports, self.sem.qua_len) 
                else:
                    if self.sym[1] == '_':
                        raise Exception("[Sytax Error] expexted {} before {} on line {}".format('\';\'',self.sym[0],self.sem.row))
                    else:
                        raise Exception("[Sytax Error] expexted {} before {} on line {}".format('\';\'',self.sym[1],self.sem.row))
        elif self.sym[0] == 5: #控制语句，条件语句
            if self.sym[1] == 'if':
                self.G(chain, control)
            elif self.sym[1] == 'while':
                self.H(chain)
            elif self.sym[1] == 'for':
                self.I(chain)
            elif self.sym[1] == 'goto':
                self.J()
            elif self.sym[1] == 'break':
                self.K1(control)
            elif self.sym[1] == 'continue':
                self.K2(control)
            elif self.sym[1] == 'return':
                self.R()
            else:
                raise Exception("[Sytax Error] Illegal statement {} on line {}".format(self.sym[1],self.sem.row))
        elif self.sym[0] == '{': #块语句
            self.block(control)
        elif self.sym[0] == ';': #空语句
            self.sym = self.getsym()
        else: #表达式或布尔表达式
            position = self.aheadp
            row = self.sem.row
            isbool = False
            zipper = [[],[]]
            pre_qua_len = self.sem.qua_len
            pre_temp_name = self.sem.temp_name
            try:
                self.exp()
                if self.sym[0] != ';':
                    raise Exception()
            except:
                #删掉已经产生的四元式
                now_qua_len = self.sem.qua_len
                self.sem.qua_len = pre_qua_len
                self.sem.temp_name = pre_temp_name
                for qua_index in range(now_qua_len - pre_qua_len):
                    self.sem.quaternion.pop(pre_qua_len)
                isbool = True
                self.relocat(position, row) #回溯
                self.bool1(zipper)
            if self.sym[0] == ';':
                self.sym = self.getsym()
                if isbool:
                    #遇到分号，回填真假出口 
                    for exports in zipper:
                        self.sem.backpatch(exports, self.sem.qua_len) 
            else:
                if self.sym[1] == '_':
                    raise Exception("[Sytax Error] expexted {} before {} on line {}".format('\';\'',self.sym[0],self.sem.row))
                else:
                    raise Exception("[Sytax Error] expexted {} before {} on line {}".format('\';\'',self.sym[1],self.sem.row))
                    
    #有真出口假出口的布尔表达式
    def bool1(self,zipper): #布尔逗号表达式
        bool1_place = [] #符号表入口地址,传递属性值
        bool1_place = self.bool2(zipper)
        while self.sym[0] == ',':
            #遇到逗号，已计算的布尔表达式无效，回填真假出口 
            for exports in zipper:
                self.sem.backpatch(exports, self.sem.qua_len)
            self.sym = self.getsym()
            bool1_place = self.bool2(zipper)
        return bool1_place
    def bool2(self, zipper): #布尔赋值表达式
        bool2_place = []
        if self.sym[0] == 'id':
            var_name = self.sym[1]
            bool2_place = self.sem.find_var(var_name)
            self.sym = self.getsym()
            isassign = True
            try:    
                operator = self.assign()
            except:
                isassign = False
            if isassign: #是赋值语句
                if bool2_place[0] == -1:
                    raise Exception('{} undeclared on line {}'.format(var_name, self.sem.row))
                zipper1 = [[],[]]
                self.bool2(zipper1)
                self.sem.backpatch(zipper1[0], self.sem.qua_len)
                T1_addr = self.sem.newtemp()
                self.sem.temp_table[T1_addr[1]][1] = self.sem.const_code['int']
                self.sem.addqua(':=', 1, '_', self.sem.temp_table[T1_addr[1]][0])
                self.sem.gen('jp', '_', '_', self.sem.qua_len + 2)
                self.sem.backpatch(zipper1[1], self.sem.qua_len)
                self.sem.addqua(':=', 0, '_', self.sem.temp_table[T1_addr[1]][0])
                self.sem.gen(operator, T1_addr, '_', bool2_place)#无临时变量
                zipper[0].append(self.sem.qua_len)
                self.sem.gen('jnz', bool2_place, '_', 0)
                zipper[1].append(self.sem.qua_len)
                self.sem.gen('jp', '_', '_', 0)
            else:
                self.sym = self.recall() #回溯
                bool2_place = self.bool3(zipper)
        else:
            bool2_place = self.bool3(zipper)
        return bool2_place        
    def bool3(self, zipper): #逻辑或表达式
        bool3_place = []
        zipper1 = [[],[]] #第一个是真出口，第二个是假出口
        bool3_place = self.bool4(zipper1)
        #todo 求逻辑表达式的值，产生四元式
        while self.sym[0] == '||':
            self.sym = self.getsym()
            self.sem.backpatch(zipper1[1], self.sem.qua_len)
            zipper2 = [[],[]]
            self.bool4(zipper2)
            for export in zipper2[0]:
                zipper1[0].append(export)   
            zipper1[1] = zipper2[1]
        zipper[0] = zipper1[0]
        zipper[1] = zipper1[1]
        return bool3_place
    def bool4(self, zipper): #逻辑与表达式
        bool4_place = []
        zipper1 = [[],[]] #第一个是真出口，第二个是假出口
        bool4_place = self.bool5(zipper1)
        #todo 求逻辑表达式的值，产生四元式
        while self.sym[0] == '&&':
            self.sym = self.getsym()
            self.sem.backpatch(zipper1[0], self.sem.qua_len)
            zipper2 = [[],[]]
            self.bool5(zipper2) 
            for export in zipper2[1]:
                zipper1[1].append(export)
            zipper1[0] = zipper2[0]
        zipper[0] = zipper1[0]
        zipper[1] = zipper1[1]
        return bool4_place
    def bool5(self, zipper): #子布尔表达式
        bool5_place = self.exp5() #属性值
        zipper[0].append(self.sem.qua_len)  
        self.sem.gen('jnz', bool5_place, '_', 0)
        zipper[1].append(self.sem.qua_len)
        self.sem.gen('jp', '_', '_', 0)
        return bool5_place
    def exp(self): #逗号表达式
        exp_place = [] #符号表入口地址,传递属性值
        exp_place = self.exp1()
        while self.sym[0] == ',':
            self.sym = self.getsym()
            exp_place = self.exp1()
        return exp_place
    def exp1(self): #赋值表达式
        exp1_place = []
        if self.sym[0] == 'id':
            var_name = self.sym[1]
            exp1_place = self.sem.find_var(var_name)
            self.sym = self.getsym()
            isassign = True
            try:    
                operator = self.assign()
            except:
                isassign = False
            if isassign: #是赋值语句
                if exp1_place[0] == -1:
                    raise Exception('{} undeclared on line {}'.format(var_name, self.sem.row))
                var_addr = self.exp1()
                self.sem.gen(operator, var_addr, '_', exp1_place)#无临时变量
            else:
                self.sym = self.recall() #回溯
                exp1_place = self.exp5()
        else:
            exp1_place = self.exp5()
        return exp1_place
    def exp5(self): #等于表达式
        exp5_place = []
        exp5_place = self.exp6()
        #todo 求逻辑表达式的值，产生四元式
        while self.sym[0] == '==' or self.sym[0] == '!=':
            operator = self.judge()
            var_addr = self.exp6()
            T1_place = self.sem.newtemp()
            self.sem.gen(operator, exp5_place, var_addr, T1_place) #传地址
            exp5_place = T1_place
        return exp5_place
    def exp6(self): #关系表达式
        exp6_place = []
        exp6_place = self.exp7()
        #todo 求关系表达式的值，产生四元式
        while self.sym[0] == '<' or self.sym[0] == '>' or self.sym[0] == '<=' or self.sym[0] == '>=':
            operator = self.rela()
            var_addr = self.exp7()
            T1_place = self.sem.newtemp()
            self.sem.gen(operator, exp6_place, var_addr, T1_place) #传地址
            exp6_place = T1_place
        return exp6_place
    def exp7(self): #移位表达式
        exp7_place = []
        exp7_place = self.exp8()
        #todo 求关系表达式的值，产生四元式
        while self.sym[0] == '>>' or self.sym[0] == '<<':
            operator = self.shift()
            var_addr = self.exp8()
            T1_place = self.sem.newtemp()
            self.sem.gen(operator, exp7_place, var_addr, T1_place) #传地址
            exp7_place = T1_place
        return exp7_place
    def exp8(self): #加法表达式
        exp8_place = []
        exp8_place = self.exp9()
        while self.sym[0] == '+' or self.sym[0] == '-':
            operator = self.coun()
            var_addr = self.exp9()
            T1_place = self.sem.newtemp()
            self.sem.gen(operator, exp8_place, var_addr, T1_place) #传地址
            exp8_place = T1_place
        return exp8_place
    def exp9(self): #乘法表达式
        exp9_place = []
        exp9_place = self.exp10()
        while self.sym[0] == '*' or self.sym[0] == '/' or self.sym[0] == '%':
            operator = self.mul()
            var_addr = self.exp10()
            T1_place = self.sem.newtemp()
            self.sem.gen(operator, exp9_place, var_addr, T1_place)
            exp9_place = T1_place
        return exp9_place
    def exp10(self): #后++
        exp10_place = []
        position = self.aheadp
        row = self.sem.row
        try:
            var_name = self.E()
            var_addr = self.sem.find_var(var_name)
            if var_addr[0] == -1:
                raise Exception("")
            operator = self.suffix()
            T1_place = self.sem.newtemp() #临时变量表新增一项,返回临时变量表入口地址
            self.sem.gen(':=', var_addr, '_', T1_place) #产生四元式，临时变量求属性值
            self.sem.gen(operator, var_addr, '_', var_addr)
            exp10_place = T1_place
        except:
            self.relocat(position, row) #回溯
            exp10_place = self.exp11()
        return exp10_place
    def exp11(self): # ！ - ++ --
        exp11_place = []
        if self.sym[0] == '!' or self.sym[0] == '-' :
            T1_place = self.sem.newtemp() #返回临时变量表入口地址
            operator = self.unary() #运算符
            operand = self.exp12() #操作数入口地址
            self.sem.gen(operator, operand, '_', T1_place) #产生四元式，临时变量求属性值
            exp11_place = T1_place #表达式值传递
        elif self.sym[0] == '++' or self.sym[0] == '--' : #前++
            operator = self.suffix()
            var_name = self.E()
            exp11_place = self.sem.find_var(var_name) #表达式值传递
            if exp11_place[0] == -1:
                raise Exception('{} undeclared on line {}'.format(var_name, self.sem.row))
            self.sem.gen(operator, exp11_place, '_', '_') #产生四元式
        else:
            exp11_place = self.exp12() #表达式值传递
        return exp11_place
    def exp12(self): #标识符，括号，常量表达式 
        exp12_place = []
        if self.sym[0] == '(':
            self.sym = self.getsym()
            exp12_place = self.exp()
            if self.sym[0] == ')':
                self.sym = self.getsym()
            else:
                raise Exception("[Sytax Error] expected {} before {} on line {}".format('\')\'', self.sym[1], self.sem.row))
        elif self.sym[0] == 'id':
            #查找id在符号表中的入口地址,若未查到，返回列表第一项为-1
            var_name = self.sym[1] #变量名
            exp12_place = self.sem.find_var(var_name)
            self.sym = self.getsym()
            if exp12_place[0] == -1: #变量未定义
                if self.sym[0] == '(': #是函数调用表达式
                     #根据函数名查找函数是否定义
                     #找到全局变量中函数的地址
                    func_place = self.sem.find_func(var_name) 
                    if func_place[0] == -1:
                        raise Exception("undefined reference to {} on line {}".format(var_name, self.sem.row))
                    self.sym = self.getsym()
                    arglist = self.arglist()
                    #根据全局变量中函数的地址产生函数栈的地址，在函数栈的地址中找到变量类型和个数，判断与arglist是否匹配
                    self.sem.judge_matches(var_name, func_place, arglist)
                    if self.sym[0] == ')':
                        self.sym = self.getsym()
                        for arg_addr in arglist: 
                            self.sem.gen('push', '_', '_', arg_addr)
                        self.sem.addqua('push', '_', '_', self.sem.qua_len + 2)
                        self.sem.addqua('Call', '_', len(arglist), var_name) #产生函数调用四元式
                        T1_addr = self.sem.newtemp() #临时变量
                        #查表得到函数类型
                        _, func_type = self.sem.find_operator(func_place) 
                        #临时变量类型为函数类型
                        self.sem.temp_table[T1_addr[1]][1] = func_type 
                        #把函数返回值给临时变量
                        self.sem.gen('pop', '_', '_', T1_addr)
                        exp12_place = T1_addr #返回临时变量
                    else:
                        if self.sym[1] == '_':
                            raise Exception("[Sytax Error] expected expression before {} token on line {}".format(self.sym[0], self.sem.row))
                        else:
                            raise Exception("[Sytax Error] expected expression before {} token on line {}".format(self.sym[1], self.sem.row))
                else: #是未定义变量
                    raise Exception('{} undeclared on line {}'.format(var_name, self.sem.row))
        elif self.sym[0] == 1 or self.sym[0] == 2 or self.sym[0] == 3: #int
            const_type = ''
            if self.sym[0] == 1:
                const_type = 'int'
            elif self.sym[0] == 2:
                const_type = 'double'
            else:
                const_type = 'char'
            exp12_place = self.sem.addconst(self.sym[1], const_type) #常量入表，返回入口地址
            self.sym = self.getsym()
        elif self.sym[0] == 4: #string
            raise Exception("[Sytax Error] string type is not supported on line {}".format(self.sem.row))
        else:
            raise Exception("[Sytax Error] illegal expression on line {}".format(self.sem.row))
        return exp12_place
    def arglist(self): #参数列表，返回所有入口参数的地址
        arglist = []
        arglist.append(self.exp1())
        while self.sym[0] == ',':
            self.sym = self.getsym()
            arglist.append(self.exp1())
        return arglist
    def unary(self): #单目运算符
        if self.sym[0] == '!' or self.sym[0] == '-':
            operator = self.sym[0]
            self.sym = self.getsym()
            return operator
    def suffix(self): # ++ --
        if self.sym[0] == '++' or self.sym[0] == '--':
            operator = self.sym[0]
            self.sym = self.getsym()
        else:
            raise Exception("[Sytax Error] illegal expression on line {}".format(self.sem.row))
        return operator
    def mul(self): #乘法运算符
        if self.sym[0] == '*' or self.sym[0] == '/' or self.sym[0] == '%':
            operator = self.sym[0]
            self.sym = self.getsym()
            return operator
    def coun(self): #加减运算符
        if self.sym[0] == '+' or self.sym[0] == '-':
            operator = self.sym[0]
            self.sym = self.getsym()
            return operator
    def shift(self): #移位运算符
        if self.sym[0] == '>>' or self.sym[0] == '<<':
            operator = self.sym[0]
            self.sym = self.getsym()
            return operator
    def rela(self): #关系运算符
        if self.sym[0] == '<' or self.sym[0] == '>' or self.sym[0] == '<=' or self.sym[0] == '>=':
            operator = self.sym[0]
            self.sym = self.getsym()
            return operator
    def judge(self): #等于运算符
        if self.sym[0] == '==' or self.sym[0] == '!=':
            operator = self.sym[0]
            self.sym = self.getsym()
            return operator
    def assign(self): #赋值运算符
        if self.sym[0] == '=' or self.sym[0] == '+=' or self.sym[0] == '-=' or self.sym[0] == '*=' or self.sym[0] == '/=' or self.sym[0] == '%=' or self.sym[0] == '<<=' or self.sym[0] == '>>=': 
            operator = self.sym[0]
            self.sym = self.getsym()
            return operator
        else:
            raise Exception("[Sytax Error] expected {} before {} on line {}".format('\';\'', self.sym[1], self.sem.row))
    def G(self, chain, control): #条件语句 if
        if self.sym[1] == 'if':
            self.sym = self.getsym()
            if self.sym[0] == '(':
                self.sym = self.getsym()
                zipper = [[],[]]
                self.bool1(zipper)
                if self.sym[0] == ')':
                    self.sym = self.getsym()
                    self.sem.backpatch(zipper[0], self.sem.qua_len) #布尔表达式的真出口
                    chain1 = []
                    self.S(chain1, control) #if后语句块的出口
                    if self.sym[1] == 'else':
                        self.tail(zipper, chain1, chain, control)
                    else:
                        #没有 else语句，if语句的出口是if后语句块的出口和布尔表达式的假出口
                        for c in zipper[1]:
                            chain.append(c)
                        for c in chain1:
                            chain.append(c)
                else:
                    if self.sym[0] == '_':
                        raise Exception("[Sytax Error] expected {} before {} token on line {}".format('\')\'',self.sym[1], self.sem.row))
                    else:
                        raise Exception("[Sytax Error] expected {} before {} token on line {}".format('\')\'',self.sym[0], self.sem.row))
            else:
                raise Exception("[Sytax Error] expected {} before numeric constant on line {}".format('\'(\'', self.sem.row))
    def tail(self, zipper, chain1, chain, control): #else
        if self.sym[1] == 'else':
            self.sym = self.getsym()
            q = self.sem.qua_len #if后面的语句执行结束，跳转出口
            self.sem.gen('jp', '_', '_', 0) 
            #回填布尔表达式的假出口，下面执行else的语句块
            self.sem.backpatch(zipper[1], self.sem.qua_len) 
            #if后语句块的出口和if后语句执行结束的出口相同
            chain1.append(q) 
            chain2 = []
            self.S(chain2, control) #else后语句块的出口
            #整个if else 语句的出口是if后语句块的出口和else后语句块的出口
            for c in chain1:
                chain.append(c)
            for c in chain2:
                chain.append(c)
    def H(self, chain): #循环语句while
        if self.sym[1] == 'while':
            self.sym = self.getsym()
            if self.sym[0] == '(':
                self.sym = self.getsym()
                quad = self.sem.qua_len #记录while后的布尔表达式位置
                zipper = [[],[]]
                self.bool1(zipper) #得到布尔表达式的拉链
                if self.sym[0] == ')':
                    self.sym = self.getsym()
                    self.sem.backpatch(zipper[0], self.sem.qua_len) #回填真出口
                    chain1 = []
                    control = [[],[]]
                    self.S(chain1, control) #while后的语句执行完跳转链
                    #回填continue 语句
                    for jumpout in control[1]:
                        self.sem.backpatch([jumpout[1]], quad)
                    self.sem.backpatch(chain1, quad) #while内语句块跳转出口回填
                    self.sem.gen('jp', '_', '_', quad) #回到布尔表达式
                    #while语句的出口是布尔表达式的假出口和break的跳转出口
                    for export in zipper[1]:
                        chain.append(export)
                    for jumpout in control[0]:
                        chain.append(jumpout[1])
                else:
                    if self.sym[0] == '_':
                        raise Exception("[Sytax Error] expected {} before {} token on line {}".format('\')\'',self.sym[1], self.sem.row))
                    else:
                        raise Exception("[Sytax Error] expected {} before {} token on line {}".format('\')\'',self.sym[0], self.sem.row))
            else:
                raise Exception("[Sytax Error] expected {} before numeric constant on line {}".format('\'(\'', self.sem.row))
        pass
    def I(self, chain): #循环语句for
        if self.sym[1] == 'for':
            self.sym = self.getsym()
            if self.sym[0] == '(':
                self.sym = self.getsym()
                self.exp()
                if self.sym[0] == ';':
                    self.sym = self.getsym()
                    quad1 = self.sem.qua_len #for后的布尔表达式位置
                    zipper = [[],[]] #记录真假出口
                    self.bool1(zipper) #获得真假出口
                    if self.sym[0] == ';':
                        self.sym = self.getsym()
                        quad2 = self.sem.qua_len #for的第三个表达式的四元式位置
                        self.exp()
                        self.sem.gen('jp', '_', '_', quad1)
                        if self.sym[0] == ')':
                            self.sym = self.getsym()
                            self.sem.backpatch(zipper[0], self.sem.qua_len) #回填布尔表达式的真出口
                            chain1 = []
                            control = [[],[]]
                            self.S(chain1, control)
                            #回填continue 语句
                            for jumpout in control[1]:
                                self.sem.backpatch([jumpout[1]], quad2)
                            self.sem.backpatch(chain1, quad2) #for内块语句出口回填
                            self.sem.gen('jp', '_', '_', quad2)
                            #for语句的出口是布尔表达式的假出口和break语句的出口
                            for export in zipper[1]: 
                                chain.append(export)
                            for jumpout in control[0]:
                                chain.append(jumpout[1])
                        else:
                            if self.sym[0] == '_':
                                raise Exception("[Sytax Error] expected {} before {} token on line {}".format('\')\'',self.sym[1], self.sem.row))
                            else:
                                raise Exception("[Sytax Error] expected {} before {} token on line {}".format('\')\'',self.sym[0], self.sem.row))
                    else:
                        if self.sym[0] == '_':
                            raise Exception("[Sytax Error] expected {} before {} on line {}".format('\';\'',self.sym[1], self.sem.row))
                        else:
                            raise Exception("[Sytax Error] expected {} before {} on line {}".format('\';\'',self.sym[0], self.sem.row))
                else:
                    if self.sym[0] == '_':
                        raise Exception("[Sytax Error] expected {} before {} on line {}".format('\';\'',self.sym[1], self.sem.row))
                    else:
                        raise Exception("[Sytax Error] expected {} before {} on line {}".format('\';\'',self.sym[0], self.sem.row))
            else:
                if self.sym[0] == '_':
                    raise Exception("[Sytax Error] expected {} before {} on line {}".format('\'(\'',self.sym[1], self.sem.row))
                else:
                    raise Exception("[Sytax Error] expected {} before {} on line {}".format('\'(\'',self.sym[0], self.sem.row))
    def J(self): #goto
        if self.sym[1] == 'goto':
            self.sym = self.getsym()
            label_name = self.E()
            label_addr = self.sem.find_label(label_name)
            if label_addr[0] == -1: #未查到
                self.sem.table[-1][self.sem.var_block].append([label_name, 2, 0, 0, self.sem.qua_len]) #填符号表,地址为NXQ
                self.sem.gen('jp', '_', '_', -1)
            else: #查到了
                label, _ = self.sem.find_operator(label_addr)
                if label[3] == 0: #未定义
                    linkhead = label[4]
                    label[4] = self.sem.qua_len
                    self.sem.gen('jp', '_', '_', linkhead) #拉链
                else: #已定义
                    self.sem.gen('jp', '_', '_', label[4]) #跳转到地址
            if self.sym[0] == ';':
                self.sym = self.getsym()
            else:
                if self.sym[0] == '_':
                    raise Exception("[Sytax Error] expected {} before {} on line {}".format('\';\'',self.sym[1], self.sem.row))
                else:
                    raise Exception("[Sytax Error] expected {} before {} on line {}".format('\';\'',self.sym[0], self.sem.row))                
    def K1(self, control): #break
        if self.sym[1] == 'break':
            self.sym = self.getsym()
            control[0].append([self.sem.row, self.sem.qua_len])
            self.sem.gen('jp', '_', '_', 0)
            if self.sym[0] == ';':
                self.sym = self.getsym()
            else:
                if self.sym[0] == '_':
                    raise Exception("[Sytax Error] expected {} before {} on line {}".format('\';\'',self.sym[1], self.sem.row))
                else:
                    raise Exception("[Sytax Error] expected {} before {} on line {}".format('\';\'',self.sym[0], self.sem.row))
    def K2(self, control): #continue
        if self.sym[1] == 'continue':
            self.sym = self.getsym()
            control[1].append([self.sem.row, self.sem.qua_len])
            self.sem.gen('jp', '_', '_', 0)
            if self.sym[0] == ';':
                self.sym = self.getsym()
            else:
                if self.sym[0] == '_':
                    raise Exception("[Sytax Error] expected {} before {} on line {}".format('\';\'',self.sym[1], self.sem.row))
                else:
                    raise Exception("[Sytax Error] expected {} before {} on line {}".format('\';\'',self.sym[0], self.sem.row))        
    def R(self): #控制语句return
        if self.sym[1] == 'return':
            self.sym = self.getsym()
            #返回地址临时变量
            T1_place = self.sem.newtemp()
            self.sem.temp_table[T1_place[1]][1] = self.sem.const_code['int'] #临时变量类型为整型
            self.sem.gen('pop', '_', '_', T1_place) #从栈中取出返回地址给临时变量
            var_name = self.exp()
            #返回值临时变量
            T2_place = self.sem.newtemp()
            #为临时变量赋值和类型
            self.sem.gen(':=', var_name, '_', T2_place)
            #判断临时变量类型和函数类型是否匹配，返回函数应该返回的值
            return_value = self.sem.judge_return(T2_place)
            self.sem.gen('push', '_', '_', return_value) #返回值入栈
            self.sem.addqua('jp', '_', '_', self.sem.temp_table[T1_place[1]][0]) #跳转到返回地址
            if self.sym[0] == ';':
                self.sym = self.getsym()
            else:
                if self.sym[0] == '_':
                    raise Exception("[Sytax Error] expected {} before {} on line {}".format('\';\'',self.sym[1], self.sem.row))
                else:
                    raise Exception("[Sytax Error] expected {} before {} on line {}".format('\';\'',self.sym[0], self.sem.row))
    def label(self): #标号语句
        if self.sym[0] == 'id':
            label_name = self.sym[1] #标号名
            self.sym = self.getsym()
            if self.sym[0] == ':':
                self.sym = self.getsym()
                #确定是标号语句
                label_addr = self.sem.find_label(label_name) #查找标号的地址
                if label_addr[0] == -1: #若没有标号，填入符号表
                    self.sem.table[-1][self.sem.var_block].append([label_name, 2, 0, 1, self.sem.qua_len])
                else: #若有标号查看是否定义
                    label, _ = self.sem.find_operator(label_addr)
                    if label[3] == 0: #标号未定义
                        label[3] = 1 #改为已定义
                        self.sem.backfill(label[4], self.sem.qua_len) #拉链回填
                    else: #标号已定义,认为不是标号语句
                        raise Exception()
            else:
                raise Exception("[Sytax Error] {} undeclared on line {}".format(self.sym[1],self.sem.row))
fam = Fam()
fam.main()
synax = Syntax(fam.output)
synax.main()
quaternion = '' #要输出的四元式
for qua, line in zip(synax.sem.quaternion, range(synax.sem.qua_len)):
    quaternion += f"{line}    ({qua[0]}, {qua[1]}, {qua[2]}, {qua[3]})\n"
file = open("quaternion.txt", "w")
file.write(quaternion)
file.close()

